package com.qire.common.widget.adapter.auto;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.ViewGroup;

import com.qire.common.basic.ObjectUtil;
import com.qire.common.collect.ListUtil;
import com.qire.common.widget.adapter.auto.annotation.AdapterEntityBind;
import com.youth.banner.Banner;
import com.youth.banner.adapter.BannerAdapter;

import java.util.List;

import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;

import com.qire.common.widget.adapter.auto.SummerBannerAdapter.BannerViewHolder;
import com.youth.banner.util.BannerUtils;

/**
 * 基于 {@link Banner} 控件扩展的自动适配器，支持到jetPack dataBind框架
 * @see BannerAdapter
 * @param <T> 数据viewModel类型 类型必须实现 {@link AutoVariable} 接口，并且使用 {@link AdapterEntityBind} 描述绑定的XML布局
 *           或者构建时传递 xml 布局的 layoutID
 */
public class SummerBannerAdapter<T extends AutoVariable> extends BannerAdapter<T, BannerViewHolder> {

    /** 无效ID */
    private static final int INVALID = -1;

    /** 事件处理器 */
    private AutoVariable eventProcess;

    /** ViewModel类型，需要从中获取 {@link AdapterEntityBind} 注解读取LayoutRid*/
    private Class<?> clz;

    /** layoutRid 用于构建项目RootView */
    private int rootViewId = INVALID;

    /**
     * 通过ViewModel提取layoutRid，如果dataList为空，则无法提取会并会导致后续异常
     * @return layoutRid
     */
    private int fetchRootViewId() {
        if(rootViewId == INVALID) {
            if(ObjectUtil.isNull(clz) && ListUtil.notEmpty(mDatas)) {
                clz = mDatas.get(0).getClass();
            }
            if(ObjectUtil.nonNull(clz) && clz.isAnnotationPresent(AdapterEntityBind.class)) {
                AdapterEntityBind adapterEntityBind = clz.getAnnotation(AdapterEntityBind.class);
                rootViewId = adapterEntityBind.viewRid();
            }
        }
        return rootViewId;
    }

    /**
     * 提供一个只接受数据ViewModel列表的构造方式
     * @param dataList dataList 包含子项数据的ViewModel
     */
    public SummerBannerAdapter(@NonNull List<T> dataList) {
        this(dataList, null);
    }

    /**
     * 提供一个在构建之初就绑定事件处理器的构造方式
     * @param dataList dataList 包含子项数据的ViewModel
     * @param eventProcess 交互事件处理器
     */
    public SummerBannerAdapter(@NonNull List<T> dataList, AutoVariable eventProcess) {
        this(dataList, eventProcess, INVALID);
        fetchRootViewId();
    }

    /**
     *  提供一个指定布局方式的构造器
     * @param dataList dataList 包含子项数据的ViewModel
     * @param rootViewId 指定布局Rid
     */
    public SummerBannerAdapter(@NonNull List<T> dataList, @LayoutRes int rootViewId) {
        this(dataList, null, rootViewId);
    }

    /**
     * 提供一个完整参数的构造器
     * @param dataList dataList 包含子项数据的ViewModel
     * @param eventProcess 交互事件处理器
     * @param rootViewId 指定布局Rid
     */
    public SummerBannerAdapter(@NonNull List<T> dataList, AutoVariable eventProcess, @LayoutRes int rootViewId) {
        super(dataList);
        this.eventProcess = eventProcess;
        this.rootViewId = rootViewId;
    }

    @Override
    public int getItemCount() {
        // todo: 临时修复banner无限循环中关于真实位置计算的错误，需要之后重写无限滚动控件来处理，或者copy框架源码修复
        return Integer.MAX_VALUE;
    }

    /**
     * {@link BannerUtils#getRealPosition} 存在问题，现有的模式会导致多计算一个点
     * @param position
     * @return
     */
    @Override
    public int getRealPosition(int position) {
        // todo: 临时修复banner无限循环中关于真实位置计算的错误，需要之后重写无限滚动控件来处理，或者copy框架源码修复
        return position % getRealCount();
    }

    /**
     * 设置事件处理器到所有项目View并进行绑定
     * @param eventProcess 事件处理器
     */
    public void setEventProcess(AutoVariable eventProcess) {
        this.eventProcess = eventProcess;
        notifyDataSetChanged();
    }

    private ViewDataBinding fetchRootView(Context context, ViewGroup viewGroup) {
        LayoutInflater layoutInflater = LayoutInflater.from(context);
        return DataBindingUtil.inflate(layoutInflater,fetchRootViewId(), viewGroup, false);
    }

    @Override
    public BannerViewHolder onCreateHolder(ViewGroup parent, int viewType) {
        ViewDataBinding viewDataBinding = fetchRootView(parent.getContext(), parent);
        BannerViewHolder viewHolder = new BannerViewHolder(viewDataBinding);
        return viewHolder;
    }

    @Override
    public void onBindView(BannerViewHolder viewHolder, T data, int position, int size) {
        viewHolder.bindData(data);
        viewHolder.bindData(eventProcess);
    }

    /**
     * 缓存binder的处理器，负责绑定数据
     */
    protected static class BannerViewHolder extends ViewHolder {
        protected final ViewDataBinding viewDataBinding;

        public BannerViewHolder(@NonNull ViewDataBinding viewDataBinding) {
            super(viewDataBinding.getRoot());
            this.viewDataBinding = viewDataBinding;
        }

        public void bindData(AutoVariable observable) {
            if(observable != null) {
                observable.bindVariable(viewDataBinding);
            }
        }
    }

}
